//  Copyright (c) 2024 Huawei Technologies Co., Ltd.
//  openUBMC is licensed under Mulan PSL v2.
//  You can use this software according to the terms and conditions of the Mulan PSL v2.
//  You may obtain a copy of Mulan PSL v2 at:
//        #  http://license.coscl.org.cn/MulanPSL2
//  THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
//  EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
//  MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
//  See the Mulan PSL v2 for more details.
import { UI_REST_GENERALDOWNLOAD, UI_REST_SYSTEM_THERMAL } from '@/api/api';
import $http from '@/utils/http-service';
import { traduction } from '@/utils/language';
import imgUrl from '@/assets/common/image/line.png';
import { reauthHandler } from '@/utils/sensitive';

export interface PowerSupplyMode {
  operateState: SwitchStatus;
  currentPowerSupplyMode: number;
  expectedPowerSupplyMode: number;
}

export enum SwitchStatusText {
  RUNNING = 'POWER_SUPPLY_SWITCH_RUNNING',
  FINISHED = 'POWER_SUPPLY_SWITCH_FINISHED',
  FAILED = 'POWER_SUPPLY_SWITCH_FAILED',
  IDLE = 'POWER_SUPPLY_SWITCH_IDLE',
}

export enum SwitchStatus {
  IDLE = 0,
  RUNNING = 1,
  FINISHED = 2,
  FAILED = 3,
}

export const switchStatusMap = new Map<SwitchStatus, SwitchStatusText>([
  [SwitchStatus.IDLE, SwitchStatusText.IDLE],
  [SwitchStatus.RUNNING, SwitchStatusText.RUNNING],
  [SwitchStatus.FINISHED, SwitchStatusText.FINISHED],
  [SwitchStatus.FAILED, SwitchStatusText.FAILED],
]);

// 电源信息
export function getpowerSupply(): Promise<any> {
  return $http.get('/UI/Rest/System/PowerSupply');
}
// 电源转换器信息
export function getPowerConverter(): Promise<any> {
  return $http.get('/UI/Rest/System/PowerConverter');
}

export function setPowerSupply(param: any): Promise<any> {
  return $http.patch('/UI/Rest/System/PowerSupply', param);
}

export function getPower(id?: string): Promise<any> {
  if (id) {
    return $http.get(`/UI/Rest/System/Power?SystemId=${Number(id.slice(6))}`);
  } else {
    return $http.get('/UI/Rest/System/Power');
  }
}

export function getPowerCount(): Promise<any> {
  return $http.get('/UI/Rest/System/SystemCount');
}

export function getPowerHistory(dataType: string, id?: string): Promise<any> {
  if (id) {
    return $http.get(`/UI/Rest/System/Power/HistoricalPower?Domain=${dataType}&SystemId=${Number(id.slice(6))}`);
  } else {
    return $http.get(`/UI/Rest/System/Power/HistoricalPower?Domain=${dataType}`);
  }
}

export function setPower(param: any): Promise<any> {
  return $http.patch('/UI/Rest/System/Power', param);
}

// 电源控制
export function getPowerControl(): Promise<any> {
  return $http.get('/UI/Rest/System/PowerControl');
}

export function setPowerControl(param: any): Promise<any> {
  return $http.patch('/UI/Rest/System/PowerControl', param);
}

export function resetPowerCapping(): Promise<any> {
  return $http.post('/UI/Rest/System/Power/ResetStatistics', {});
}

export function clearHistoryData(dataType: string, id?: string): Promise<any> {
  let params = {
    DataType: dataType,
  } as any;
  if (id && dataType !== 'System') {
    params.SystemId = Number(id.slice(6));
  }
  return $http.delete('/UI/Rest/System/Power/History', params);
}

export function setPowerOnOff(param: any, id?: string): Promise<any> {
  let obj = {
    OperateType: param?.OperateType || '',
  } as any;
  if (param?.OperateType.indexOf('_') > -1) {
    obj.OperateType = param.OperateType.split('_')[0];
    obj.FruID = Number(param.OperateType.split('_')[1]);
  } else {
    obj.FruID = 0;
  }
  if (id) {
    obj.SystemId = id;
  }
  return $http.post('/UI/Rest/System/PowerControl', obj);
}

export function downLoadHistory(dataType: string, id?: string): Promise<any> {
  let params = {
    DataType: dataType,
  } as any;
  if (id && dataType !== 'System') {
    params.SystemId = Number(id.slice(6));
  }
  return $http.post('/UI/Rest/System/Power/History', params);
}

export function queryProgress(url: string) {
  return $http.get(url);
}

export function getThermals(): Promise<any> {
  return $http.get(UI_REST_SYSTEM_THERMAL);
}

export function getPowerEnergy(): Promise<any> {
  return $http.get('/UI/Rest/System/EnergySavingMeasurement');
}

// 获取当前节能设置模式
export function getEnergySavingService(): Promise<any> {
  return $http.get('/UI/Rest/System/EnergySavingService');
}
// 获取当前Preformance Profile模式数据
export function getEnergySavingServiceScenes(type: string): Promise<any> {
  return $http.get(`/UI/Rest/System/EnergySavingService/Scenes?Type=${type}`);
}
// 设置节能模式
export function setEnergyServiceScenes(param: any): Promise<any> {
  return $http.patch('/UI/Rest/System/EnergySavingService', param);
}
// 设置节能模式
export function setBiosSettings(param: any): Promise<any> {
  return $http.patch('/UI/Rest/System/Bios/Settings', param);
}
// 下载不同类型下载文件
export function downloadData(type: string) {
  const data = {
    System: {
      Path: '/tmp/history.csv',
      TransferProtocol: 'HTTPS',
    },
    Cpu: {
      Path: '/tmp/cpu_history.csv',
      TransferProtocol: 'HTTPS',
    },
    Fan: {
      Path: '/tmp/fan_history.csv',
      TransferProtocol: 'HTTPS',
    },
    Memory: {
      Path: '/tmp/memory_history.csv',
      TransferProtocol: 'HTTPS',
    },
  };
  return $http.post(UI_REST_GENERALDOWNLOAD, data[type as keyof typeof data || 'System'], { responseType: 'blob' });
}

export async function getPowerSupplyMode(): Promise<PowerSupplyMode | null> {
  const res = await $http.get('/UI/Rest/System/PowerSupply/PowerSupplySource');
  return res.data ? {
    operateState: res.data.OperateState,
    currentPowerSupplyMode: res.data.CurrentSupplySource,
    expectedPowerSupplyMode: res.data.ExpectedSupplySource,
  } : null;
}

export async function getPowerSwitchProgress(): Promise<number> {
  const res = await $http.get('/UI/Rest/System/PowerSupply/PowerSupplySource/GetOperationTaskProgress');
  const progressLiteral = res.data?.OperateProgress;
  if (!progressLiteral) {
    return -1;
  }
  return parseInt(progressLiteral.split('%')[0], 10);
}

export async function setPowerSupplyMode(source: number, pwd?: string): Promise<void> {
  const params = { ['SupplySource']: source, ...pwd ? { ReauthKey: pwd } : {} };
  await reauthHandler(params).post('/UI/Rest/System/PowerSupply/PowerSupplySource/SetPowerSupplySource', params);
}

function generateXLabels(timeArray: any) {
  const start = new Date(timeArray[timeArray.length - 1]).getTime();
  const end = new Date(timeArray[0]).getTime();
  const len = Math.ceil((start - end) / 600000);
  const intervals = [
    { len: 11, interval: 600 * 1000 }, // 10分钟
    { len: 16, interval: 900 * 1000 }, // 15分钟
    { len: 31, interval: 1800 * 1000 }, // 30分钟
    { len: 61, interval: 3600 * 1000 }, // 1个小时
    { len: 121, interval: 2 * 3600 * 1000 }, // 2个小时
    { len: 361, interval: 6 * 3600 * 1000 }, // 6个小时
    { len: 721, interval: 12 * 3600 * 1000 }, // 12个小时
    { len: 1009, interval: 24 * 3600 * 1000 }, // 24个小时
    { len: Infinity, interval: Math.ceil((start - end) / 9) }, // 其他情况
  ];

  for (const { len: checkLen, interval } of intervals) {
    if (len < checkLen) {
      return interval;
    }
  }
  return Math.ceil((start - end) / 9);
}
export function renderPredictedPower(
  name: string,
  series1List: Array<any>,
  series2List: Array<any>,
  echarts: any,
) {
  const timeList = series1List.map(e => e.time);
  const options = {
    color: ['#0077FF', '#29A370'],
    tooltip: getTooltip(false),
    legend: {
      type: 'scroll',
      data: [{
        icon: 'rect',
        name: traduction('POWER_PREDICTED_CURVE'),
      }, {
        name: traduction('POWER_SAVED_CURVE'),
        icon: 'rect',
      }],
    },
    grid: {
      left: 15,
      right: 32,
      top: 70,
      bottom: 0,
      containLabel: true,
    },
    xAxis: getXAxis(timeList),
    yAxis: getYAxis(name),
    series: [getSeriesPredicted(series1List, echarts), getSeriesSaved(series2List, echarts)],
  };
  return options;
}

export function renderPower(
  name: string,
  series1List: Array<any>,
  series2List: Array<any>,
  echarts: any,
) {
  const timeList = series1List.map(e => e.time);
  const options = {
    color: ['#29A370', '#E32020'],
    tooltip: getTooltip(true),
    legend: {
      type: 'scroll',
      data: [{
        name: traduction('POWER_REALTIME_CURVE'),
        icon: 'rect',
      }, {
        name: traduction('POWER_ENERGY_BEFORE'),
        icon: `image://
              ANSUhEUgAAABAAAAAEAQMAAAC9ei2vAAAAAXNSR0IB2cksfwAAAAZQTFRF8
              QsL////28bjcQAAAA1JREFUeJxjsJBhgCEACCQBUeGgHQQAAAAASUVORK5CYII=`,
      }],
    },
    grid: {
      left: 15,
      right: 32,
      top: 70,
      bottom: 0,
      containLabel: true,
    },
    xAxis: getXAxis(timeList),
    yAxis: getYAxis(name),
    series: [getSeriesRealTime(series1List, echarts), getSeriesBefore(series2List)],
  };
  return options;
}
function getIndex(value: number): number {
  let index = 0;
  if (value > 80) { // 优秀
    index = 2;
  } else if (value > 60) { // 良好
    index = 1;
  } else { // 一般
    index = 0;
  }
  return index;
}
function getTitle(title: string, length: number): string {
  let text = '';
  let count = Math.ceil(title.length / length); // 向上取整数
  if (count > 1) {
    for (let z = 1; z <= count; z++) {
      text += title.substr((z - 1) * length, length);
      if (z < count) {
        text += '\n';
      }
    }
  } else {
    text += title.substr(0, length);
  }
  return text;
}
export function renderGaugeChart(data: Array<{
  value: number;
}>, title: string): any {
  let value = data[0].value;
  let index = getIndex(value);
  let options = {
    color: [['#EBAF00', '#07F', '#24ab36'][index]],
    series: [
      {
        isCenterBg: true,
        type: 'pie',
        radius: '56%',
        label: {
          with: 60,
          overflow: 'break',
          formatter: `{b|${getTitle(title, 14)}}\n{t|${value === 0 ? '--' : value}}`,
          rich: {
            t: {
              fontSize: 32,
              lineHeight: 40,
              color: '--o-text-color-primary',
            },
          },
        },
      },
      {
        type: 'gauge',
        min: 0,
        max: 100,
        data,
        splitNumber: 4,
        axisLabel: {
          distance: -10,
        },
        axisTick: {
          splitNumber: 10,
        },
      },
    ],
  };
  return options;
}
function getSeriesBefore(valueList: Array<any>): any {
  const options = {
    name: traduction('POWER_ENERGY_BEFORE'),
    data: valueList?.map((item: any, index: any, arr: any) => {
      if (arr.length === 1) {
        return item;
      }
      return [new Date(item.time).getTime(), item.value];
    }) || [],
    type: 'line',
    lineStyle: {
      type: 'dashed',
      color: '#E32020',
    },
    emphasis: {
      lineStyle: {
        width: 2,
      },
    },
    smooth: true,
    showSymbol: false,
  };
  return options;
}
function getSeriesRealTime(valueList: Array<any>, echarts: any): any {
  const options = {
    name: traduction('POWER_REALTIME_CURVE'),
    data: valueList?.map((item: any, index: any, arr: any) => {
      if (arr.length === 1) {
        return item;
      }
      return [new Date(item.time).getTime(), item.value];
    }) || [],
    type: 'line',
    smooth: true,
    showSymbol: false,
  };
  const extern = {
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        {
          offset: 0,
          color: 'rgba(41,163,112,0.39)',
        },
        {
          offset: 0.34,
          color: 'rgba(41,163,112,0.25)',
        },
        {
          offset: 1,
          color: 'rgba(41,163,112,0.00)',
        },
      ]),
    },
  };
  Object.assign(options, extern);
  return options;
}

function getSeriesSaved(valueList: Array<any>, echarts: any): any {
  const options = {
    name: traduction('POWER_SAVED_CURVE'),
    data: valueList?.map((item: any, index: any, arr: any) => {
      if (arr.length === 1) {
        return item;
      }
      return [new Date(item.time).getTime(), item.value];
    }) || [],
    type: 'line',
    smooth: true,
    showSymbol: false,
  };
  const extern = {
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        {
          offset: 0,
          color: 'rgba(41,163,112,0.39)',
        },
        {
          offset: 0.34,
          color: 'rgba(41,163,112,0.25)',
        },
        {
          offset: 1,
          color: 'rgba(41,163,112,0.00)',
        },
      ]),
    },
  };
  Object.assign(options, extern);
  return options;
}

function getSeriesPredicted(valueList: Array<any>, echarts: any): any {
  const options = {
    name: traduction('POWER_PREDICTED_CURVE'),
    data: valueList?.map((item: any, index: any, arr: any) => {
      if (arr.length === 1) {
        return item;
      }
      return [new Date(item.time).getTime(), item.value];
    }) || [],
    type: 'line',
    smooth: true,
    showSymbol: false,
    areaStyle: {
      color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
        {
          offset: 0,
          color: 'rgba(0,119,255,0.39)',
        },
        {
          offset: 0.34,
          color: 'rgba(0,119,255,0.25)',
        },
        {
          offset: 1,
          color: 'rgba(0,119,255,0.00)',
        },
      ]),
    },
  };
  return options;
}

function getXAxis(timeList: Array<any>): any {
  return {
    type: 'category',
    interval: generateXLabels(timeList),
    boundaryGap: false,
    axisLine: {
      lineStyle: {
        color: ['var(--o-text-color-tertiary)'],
      },
    },
    axisTick: {
      show: false,
    },
    axisLabel: {
      margin: 15,
      color: '#9EA4B3',
      fontSize: 10,
      formatter(item: any): string {
        if (timeList.length === 1) {
          return (timeList[0] || '').replace(' ', '\n');
        }
        return ` ${(new Date(parseInt(item, 10)) as unknown as any).pattern('yyyy/MM/dd HH:mm').replace(' ', '\n')}`;
      },
    },
  };
}

function getYAxis(name: string): any {
  return {
    name,
    type: 'value',
    splitLine: {
      lineStyle: {
        type: 'dashed',
      },
      interval: 1,
    },
    axisLabel: {
      padding: [0, 0, 0, -20],
    },
    nameTextStyle: {
      align: 'left',
      fontFamily: 'HarmonyOS Sans SC Medium',
      padding: [0, 0, 0, -20],
    },
  };
}

function tooltipFormatter(param: any, flag: boolean): string {
  let val = '';
  for (let i = 0; i < param.length; i++) {
    const value = param[i].data?.value || param[i].data[1];
    let icon = '<span class="echarts-formatter-block"></span>';
    if (flag) {
      // 节能功率统计曲线
      icon =
        param[i].seriesIndex === 0
          ? '<span class="echarts-formatter-block sec-color"></span>'
          : `<img src=${imgUrl} class="echarts-formatter-block" />`;
    } else {
      // 节能收益预测曲线
      icon =
        param[i].seriesIndex === 0
          ? '<span class="echarts-formatter-block default-color"></span>'
          : '<span class="echarts-formatter-block sec-color"></span>';
    }
    val += `<div class="echarts-formatter-other-row-value-box">
                    ${icon}
                    <span class="echarts-formatter-key mr-8">${param[i].seriesName}</span>
                    <span class="echarts-formatter-value">${value}</span>
                  </div>`;
  }
  const time = param[0].data?.time || param[0].data[0];
  return `<span class="echarts-formatter-first-row">${(new Date(time) as unknown as any).pattern(
    'yyyy/MM/dd HH:mm',
  )}</span><br>${val}`;
}

function getTooltip(flag: boolean): any {
  return {
    trigger: 'axis',
    backgroundColor: '#fff',
    textStyle: {
      color: 'rgba(27, 25, 25, 1)',
      lineHeight: 28,
    },
    extraCssText: 'box-shadow: 0 4px 8px 0 rgba(0,0,0,0.20)',
    padding: [12, 16, 12, 16],
    borderRadius: '2',
    axisPointer: {
      lineStyle: {
        type: 'solid',
        color: 'var(--o-border-color-base)',
      },
    },
    formatter: (param: any): any => tooltipFormatter(param, flag),
  };
}
